/*
 * MediaPacketQueue.cpp
 *
 *  Created on: 2016年4月6日
 *      Author: terry
 */

#include "MediaPacketQueue.h"

namespace av
{

MediaPacketQueue::MediaPacketQueue()
{
}

MediaPacketQueue::~MediaPacketQueue()
{
}

size_t MediaPacketQueue::size()
{
    comn::AutoCritSec   lock(m_cs);
    return m_packets.size();
}

bool MediaPacketQueue::empty()
{
    comn::AutoCritSec   lock(m_cs);
    return m_packets.empty();
}

size_t MediaPacketQueue::push(MediaPacketPtr& packet)
{
    size_t count = 0;
    {
        comn::AutoCritSec   lock(m_cs);
        m_packets.push_back(packet);

        count = m_packets.size();
    }

    m_event.post();
    return count;
}

MediaPacketPtr MediaPacketQueue::pop()
{
    MediaPacketPtr packet;
    pop(packet);
    return packet;
}

bool MediaPacketQueue::pop(MediaPacketPtr& packet)
{
    bool found = false;
    comn::AutoCritSec   lock(m_cs);
    if (!m_packets.empty())
    {
        packet = m_packets.front();
        m_packets.pop_front();
        found = true;
    }
    return found;
}

void MediaPacketQueue::clear()
{
    {
        comn::AutoCritSec   lock(m_cs);
        m_packets.clear();
    }

    m_event.post();
}

bool MediaPacketQueue::timedwait(int ms)
{
    return m_event.timedwait(ms);
}

bool MediaPacketQueue::pop(MediaPacketPtr& packet, int ms)
{
    if (empty())
    {
        timedwait(ms);
    }
    return pop(packet);
}

void MediaPacketQueue::cancelWait()
{
    m_event.post();
}

int64_t MediaPacketQueue::getDuration()
{
	comn::AutoCritSec   lock(m_cs);

	if (m_packets.size() < 2)
	{
		return 0;
	}

	return m_packets.back()->pts - m_packets.front()->pts;
}

size_t MediaPacketQueue::dropUntilKeyFrame()
{
	comn::AutoCritSec   lock(m_cs);

	size_t count = 0;
	size_t toIdx = rfindVideoKey();
	if (toIdx != -1)
	{
		PacketDeque::iterator itBegin = m_packets.begin();
		PacketDeque::iterator itEnd = itBegin;
		std::advance(itEnd, toIdx);
		m_packets.erase(itBegin, itEnd);
		count = toIdx;
	}
	return count;
}

size_t MediaPacketQueue::findVideoKey()
{
	for (size_t i = 0; i < m_packets.size(); i ++)
	{
		MediaPacketPtr& pkt = m_packets[i];
		if (pkt->isVideo() && pkt->isKey())
		{
			return i;
		}
	}
	return -1;
}

size_t MediaPacketQueue::rfindVideoKey()
{
	if (m_packets.size() < 2)
	{
		return -1;
	}

	for (size_t i = m_packets.size() - 1; i != 0; i --)
	{
		MediaPacketPtr& pkt = m_packets[i];
		if (pkt->isVideo() && pkt->isKey())
		{
			return i;
		}
	}
	return -1;
}




} /* namespace av */
